package cn.com.bluemoon.daps.system.service.impl;

import cn.com.bluemoon.daps.common.domain.UserInfoHolder;
import cn.com.bluemoon.daps.common.exception.DapThrowException;
import cn.com.bluemoon.daps.system.dto.SysPageDto;
import cn.com.bluemoon.daps.system.dto.SysUserAddDto;
import cn.com.bluemoon.daps.system.dto.SysUserUpdateDto;
import cn.com.bluemoon.daps.system.entity.DapSysUser;
import cn.com.bluemoon.daps.system.entity.DapSysUserRole;
import cn.com.bluemoon.daps.system.mapper.DapSysUserMapper;
import cn.com.bluemoon.daps.system.service.DapSysUserRoleService;
import cn.com.bluemoon.daps.system.service.DapSysUserService;
import cn.com.bluemoon.daps.system.utils.SecurityUtils;
import cn.com.bluemoon.daps.system.vo.DapSysUserVo;
import cn.com.bluemoon.daps.system.vo.SysUserVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author admin
 * @since 2022-12-19
 */
@Slf4j
@Service
public class DapSysUserServiceImpl extends ServiceImpl<DapSysUserMapper, DapSysUser>
        implements DapSysUserService {

    @Autowired
    private DapSysUserRoleService sysUserRoleService;

    @Override
    public IPage<DapSysUserVo> userPage(SysPageDto pageDto) {
        LambdaQueryWrapper<DapSysUser> wrapper = new LambdaQueryWrapper<>();
        if(Objects.nonNull(pageDto.getIsUse())){
            wrapper.eq(DapSysUser::getIsUse,pageDto.getIsUse());
        }
        if(StringUtils.isNotEmpty(pageDto.getKey())){
            wrapper.and(w -> w.like(DapSysUser::getUserName, pageDto.getKey())
                    .or().like(DapSysUser::getAccount, pageDto.getKey()));
        }
        wrapper.orderByAsc(DapSysUser::getAccount);
        Page<DapSysUser> page = new Page<>(pageDto.getPageNum(), pageDto.getPageSize());
        IPage<DapSysUser> sysUserIPage = this.getBaseMapper().selectPage(page, wrapper);
        List<DapSysUserVo> userVoList = sysUserIPage.getRecords().stream().map(u -> {
            DapSysUserVo sysUserVo = new DapSysUserVo();
            BeanUtils.copyProperties(u, sysUserVo);
            return sysUserVo;
        }).collect(Collectors.toList());

        IPage<DapSysUserVo> userVoIPage = new Page<>();
        BeanUtils.copyProperties(sysUserIPage,userVoIPage);
        userVoIPage.setRecords(userVoList);
        return userVoIPage;
    }

    @Override
    public SysUserVo getUserById(Long id){
        DapSysUser sysUser = this.getById(id);
        if(Objects.isNull(sysUser)){
            throw new DapThrowException("该用户已不存在！");
        }
        SysUserVo userVo = new SysUserVo();
        BeanUtils.copyProperties(sysUser,userVo);
        //获取角色
        LambdaQueryWrapper<DapSysUserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(DapSysUserRole::getRoleId).eq(DapSysUserRole::getUserId,id);
        List<DapSysUserRole> list = sysUserRoleService.list(wrapper);
        if(!CollectionUtils.isEmpty(list)){
            userVo.setRoleIdList(list.stream().map(DapSysUserRole::getRoleId).collect(Collectors.toList()));
        }
        return userVo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean addUser(SysUserAddDto dto){
        //1.保存用户
        LambdaQueryWrapper<DapSysUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DapSysUser::getAccount,dto.getAccount());
        if(this.count(wrapper)>0){
            throw new DapThrowException("该用户已不存在！");
        }
        DapSysUser dapSysUser = new DapSysUser();
        BeanUtils.copyProperties(dto,dapSysUser);
        //密码加密
        String pwd = dto.getPassword();
        if (StringUtils.isEmpty(pwd)) {
            pwd = SecurityUtils.string2Md5(SecurityUtils.USER_INIT_PWD);
        }
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String securityPwd = "{bcrypt}" + passwordEncoder.encode(pwd);
        dapSysUser.setPassword(securityPwd);
        String account = UserInfoHolder.getAccount();
        LocalDateTime now = LocalDateTime.now();
        dapSysUser.setCreateUserId(account);
        dapSysUser.setCreateTime(now);
        dapSysUser.setUpdateUserId(account);
        dapSysUser.setUpdateTime(now);
        this.save(dapSysUser);

        //2.保存角色信息
        List<Long> roleIdList = dto.getRoleIdList();
        if(!CollectionUtils.isEmpty(roleIdList)){
            sysUserRoleService.batchSave(dapSysUser.getId(),roleIdList);
        }

        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateUser(SysUserUpdateDto dto){
        //1.保存用户
        DapSysUser dapSysUser = new DapSysUser();
        BeanUtils.copyProperties(dto,dapSysUser);
        dapSysUser.setUpdateUserId(UserInfoHolder.getAccount());
        dapSysUser.setUpdateTime(LocalDateTime.now());
        this.updateById(dapSysUser);

        //2.删角色关系
        sysUserRoleService.deleteByUserId(dto.getId());

        //3.保存新的角色关系
        if(!CollectionUtils.isEmpty(dto.getRoleIdList())){
            sysUserRoleService.batchSave(dto.getId(),dto.getRoleIdList());
        }

        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteUser(Long id){
        this.removeById(id);
        sysUserRoleService.deleteByUserId(id);
        return true;
    }

    @Override
    public boolean resetPwd(Long id, String pwd){
        DapSysUser user = this.getById(id);
        if(Objects.isNull(user)){
            throw new DapThrowException("该用户已不存在！");
        }
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String securityPwd = "{bcrypt}" + passwordEncoder.encode(pwd);
        user.setPassword(securityPwd);
        user.setUpdateUserId(UserInfoHolder.getAccount());
        user.setUpdateTime(LocalDateTime.now());
        this.updateById(user);
        return true;
    }

    @Override
    public boolean changePwd( String oldPwd, String newPwd){
        LambdaQueryWrapper<DapSysUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DapSysUser::getAccount,UserInfoHolder.getAccount());
        DapSysUser user = this.getOne(wrapper);
        if(Objects.isNull(user)){
            throw new DapThrowException("该用户已不存在！");
        }
        String password = user.getPassword();
        if (password == null || (password != null && password.indexOf("{bcrypt}") < 0)) {
            throw new DapThrowException("该用户的密码错误！");
        }
        String encodePassword = password.substring(8);
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        if (!passwordEncoder.matches(oldPwd, encodePassword)) {
            throw new DapThrowException("原密码错误！");
        }
        String newSecurityPwd = "{bcrypt}" + passwordEncoder.encode(newPwd);
        user.setPassword(newSecurityPwd);
        user.setUpdateUserId(UserInfoHolder.getAccount());
        user.setUpdateTime(LocalDateTime.now());
        this.updateById(user);
        return true;
    }
}
